﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Starxcjy.DataAccess.Sockets;
using Starxcjy.DataAccess.Sockets.Extensions;
using Starxcjy.DataAccess.Sockets.Services;
using Starxcjy.DataAccess.Sockets.Services.Implements;
using System;
using System.Diagnostics;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;


class Program2
{
    /// <summary>
    /// 根据协议 "信息一: DWS --> PLC" 构建数据包
    /// 对应 Python 的 get_plc_packet 函数
    /// </summary>
    /// <param name="waybillNo">运单号</param>
    /// <param name="slotNo">格口号</param>
    /// <returns>构建好的数据包</returns>
    public static byte[] GetPlcPacket(string waybillNo, int slotNo)
    {
        // 协议常量
        const byte SENDER_ID = 0x02;
        const byte RECEIVER_ID = 0x01;
        const byte COMMAND = 0x02;
        const int BARCODE_LEN_VALUE = 13;
        const byte SEPARATOR = 0x7C; // ASCII for '|'
        const byte END_BYTE = 0x01;

        // 1. 处理运单号：编码为ASCII，并用空格填充或截断到指定长度
        byte[] waybillBytes = new byte[BARCODE_LEN_VALUE];
        byte[] sourceBytes = Encoding.ASCII.GetBytes(waybillNo);

        // 用空格 (ASCII 0x20) 填充目标数组
        for (int i = 0; i < waybillBytes.Length; i++)
        {
            waybillBytes[i] = 0x20; // ASCII for space ' '
        }
        // 将源数据复制到目标数组，如果源更长则会被截断
        Array.Copy(sourceBytes, waybillBytes, Math.Min(sourceBytes.Length, waybillBytes.Length));

        // 2. 使用 List<byte> 动态构建数据包，这比直接操作数组更方便
        var packetList = new List<byte>
        {
            SENDER_ID,
            RECEIVER_ID,
            COMMAND,
            (byte)slotNo, // 注意：需要将 int 强制转换为 byte
            (byte)BARCODE_LEN_VALUE
        };

        packetList.AddRange(waybillBytes);
        packetList.Add(SEPARATOR);
        packetList.Add(END_BYTE);

        // 3. 在包头插入总长度
        // 协议图例中的 0x14 (十进制20) 包含了长度字节本身
        int totalLength = packetList.Count; // +1 因为要包含长度字节本身
        packetList.Insert(0, (byte)totalLength);

        // 4. 将 List<byte> 转换为最终的 byte[]
        return packetList.ToArray();
    }


    static ITcpServerService tcp01;


    static async Task Main()
    {
        Queue<int> queue = new Queue<int>();
        IServiceCollection services=new ServiceCollection();
        services.AddSocketService();
        services.AddLogging(o => o.AddConsole());


        IServiceProvider serviceProvider = services.BuildServiceProvider();

        ILogger<Program2> logger = serviceProvider.GetRequiredService<ILogger<Program2>>();

        Task.Run(async() =>
        {
            ITcpServerService tcpServerService = serviceProvider.GetService<ITcpServerService>();
            var res = await tcpServerService.OpenAsync(new Starxcjy.DataAccess.Sockets.Models.TcpServerOption()
            {
                
                    Port = 3600,
            });
            if (res.IsSuccess)
            {

                Console.WriteLine("TCP Server started successfully on port 3600.");
                tcpServerService.OnClientJoin += async (client) =>
                {

                    Console.WriteLine($"Client {client.IpAddress} connected.");
                };
                tcpServerService.OnClientClosing += (client) =>
                {
                    Console.WriteLine($"Client {client.IpAddress} disconnected.");
                };


                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                Stopwatch stopwatch = Stopwatch.StartNew();
                while (!cancellationTokenSource.IsCancellationRequested)
                {
                    bool fg = false;
                    if(tcpServerService.TcpClients.Count() > 0)
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            foreach (var item in tcpServerService.TcpClients)
                            {
                                string waybillNo = $"WBL6660566{i:D3}"; // 生成运单号 WBL000, WBL001, ..., WBL009


                                int cell = (int)Random.Shared.NextInt64(1,12);


                                var data = GetPlcPacket(waybillNo, cell);
                                await item.SendAsync(data, TimeSpan.FromSeconds(1));
                                Task.Delay(1000).Wait(); // 等待1.5秒
                                queue.Enqueue(cell);
                                Console.WriteLine($"Sent packet for waybill {waybillNo} to client {item.IpAddress}.");
                            }
                        }
                        fg = true;
                    }
                    if(fg)
                        break;
                    
                }




            }
            else
            {
                Console.WriteLine("Failed to start TCP Server: {ErrorMessage}");
            }

           

        });



        Task.Run(async () =>
        {
            ITcpServerService tcpServerService2 = serviceProvider.GetService<ITcpServerService>();
            var res = await tcpServerService2.OpenAsync(new Starxcjy.DataAccess.Sockets.Models.TcpServerOption()
            {
                Port = 2006,
            });



            if (res.IsSuccess)
            {
                Console.WriteLine("TCP Server started successfully on port 2006.");
                tcpServerService2.OnClientJoin += async (client) =>
                {
                    Console.WriteLine($"Client {client.IpAddress} connected.");
                };
                tcpServerService2.OnClientClosing += (client) =>
                {
                    Console.WriteLine($"Client {client.IpAddress} disconnected.");
                };


                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                Stopwatch stopwatch = Stopwatch.StartNew();
                while (!cancellationTokenSource.IsCancellationRequested)
                {

                    foreach (var item in tcpServerService2.TcpClients)
                    {
                        if (queue.Count > 0)
                        {
                            int cell = queue.Dequeue();
                            _=Task.Run(async () =>
                            {
                                for (int i = 0; i < (cell + 1) / 2; ++i)
                                {
                                    byte[] data = [(byte)i];
                                    await item.SendAsync(data, TimeSpan.FromSeconds(1));
                                    Task.Delay(366).Wait(); // 等待1.5秒
                                }
                            });
                        }
                    }
                    Task.Delay(10).Wait();
                }
            }
            else
            {
                Console.WriteLine("Failed to start TCP Server: {ErrorMessage}");
            }
        });



        Console.ReadLine();


    }


}



//using System.Text.Json;
//using System.Collections.Generic;

//// 1. 定义你的数据模型类
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

//// 2. 转换代码
//string jsonString = @"[
//    {""Id"":1, ""Name"":""Alice"", ""Age"":30},
//    {""Id"":2, ""Name"":""Bob"", ""Age"":25}
//]";

//// 使用内置 JSON 解析器
//List<Person> people = JsonSerializer.Deserialize<List<Person>>(jsonString);

//// 可选：配置解析选项（如属性名不区分大小写）
//var options = new JsonSerializerOptions
//{
//    PropertyNameCaseInsensitive = true // 允许 JSON 键不匹配大小写
//};
//List<Person> people = JsonSerializer.Deserialize<List<Person>>(jsonString, options);